package io.github.echarts.model.context;

import io.github.echarts.option.EChartOption;
import io.github.echarts.option.series.BarSeries;
import io.github.echarts.option.series.LineSeries;
import io.github.echarts.option.series.PieSeries;
import io.github.echarts.option.series.SeriesOption;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 图表类型检测器
 * <p>
 * 根据配置选项和数据特征检测并推荐图表类型
 * </p>
 */
public class ChartTypeDetector {

    /**
     * 安全地获取数据特征Map
     * 
     * @param context 配置上下文
     * @return 数据特征Map，如果不存在则返回空Map
     */
    @SuppressWarnings("unchecked")
    private static Map<String, Boolean> getDataFeatures(ConfigurationContext context) {
        Object featuresObj = context.getInfo("dataFeatures");
        if (featuresObj == null) {
            return new HashMap<>();
        }
        
        // 如果已经是Map<String, Boolean>类型
        if (featuresObj instanceof Map) {
            try {
                Map<?, ?> mapObj = (Map<?, ?>) featuresObj;
                
                // 检查键是否为String类型，值是否为Boolean类型
                boolean isValidMap = true;
                for (Map.Entry<?, ?> entry : mapObj.entrySet()) {
                    if (!(entry.getKey() instanceof String) || !(entry.getValue() instanceof Boolean)) {
                        isValidMap = false;
                        break;
                    }
                }
                
                if (isValidMap) {
                    return (Map<String, Boolean>) mapObj;
                }
            } catch (Exception e) {
                // 转换失败，返回空Map
            }
        }
        
        return new HashMap<>();
    }
    
    /**
     * 从配置选项检测图表类型
     * 
     * @param option ECharts配置选项
     * @param context 配置上下文
     * @return 检测到的图表类型
     */
    public static ChartType detectChartType(EChartOption option, ConfigurationContext context) {
        // 从配置选项判断图表类型
        ChartType typeFromOption = detectFromOption(option);
        
        if (typeFromOption != ChartType.UNKNOWN) {
            return typeFromOption;
        }
        
        // 从数据特征推断图表类型
        return detectFromDataFeatures(context);
    }
    
    /**
     * 从配置选项检测图表类型
     * 
     * @param option 配置选项
     * @return 检测到的图表类型
     */
    private static ChartType detectFromOption(EChartOption option) {
        if (option == null || option.getSeries() == null) {
            return ChartType.UNKNOWN;
        }
        
        // 检查系列类型
        Object seriesObj = option.getSeries();
        
        // 单个系列
        if (seriesObj instanceof SeriesOption) {
            SeriesOption series = (SeriesOption) seriesObj;
            return getChartTypeFromSeries(series);
        }
        
        // 系列列表
        if (seriesObj instanceof List) {
            @SuppressWarnings("unchecked")
            List<SeriesOption> seriesList = (List<SeriesOption>) seriesObj;
            if (!seriesList.isEmpty()) {
                // 以第一个系列类型为准
                return getChartTypeFromSeries(seriesList.get(0));
            }
        }
        
        // 系列数组
        if (seriesObj instanceof SeriesOption[]) {
            SeriesOption[] seriesArray = (SeriesOption[]) seriesObj;
            if (seriesArray.length > 0) {
                // 以第一个系列类型为准
                return getChartTypeFromSeries(seriesArray[0]);
            }
        }
        
        return ChartType.UNKNOWN;
    }
    
    /**
     * 根据系列类型获取图表类型
     * 
     * @param series 系列选项
     * @return 图表类型
     */
    private static ChartType getChartTypeFromSeries(SeriesOption series) {
        if (series == null) {
            return ChartType.UNKNOWN;
        }
        
        if (series instanceof BarSeries) {
            return ChartType.BAR;
        }
        
        if (series instanceof LineSeries) {
            return ChartType.LINE;
        }
        
        if (series instanceof PieSeries) {
            return ChartType.PIE;
        }
        
        // 根据系列类型判断
        String type = series.getType();
        if (type == null) {
            return ChartType.UNKNOWN;
        }
        
        switch (type.toLowerCase()) {
            case "bar":
                return ChartType.BAR;
            case "line":
                return ChartType.LINE;
            case "pie":
                return ChartType.PIE;
            case "scatter":
                return ChartType.SCATTER;
            case "radar":
                return ChartType.RADAR;
            default:
                return ChartType.UNKNOWN;
        }
    }
    
    /**
     * 从数据特征推断图表类型
     * 
     * @param context 配置上下文
     * @return 推断的图表类型
     */
    private static ChartType detectFromDataFeatures(ConfigurationContext context) {
        ConfigurationContext.DataStatistics stats = context.getDataStatistics();
        if (stats == null) {
            return ChartType.BAR;  // 默认为柱状图
        }
        
        // 根据数据特征推断最适合的图表类型
        int categoryCount = stats.getCategoryCount();
        int dataPointCount = stats.getDataPointCount();
        
        // 使用安全的方法获取数据特征
        Map<String, Boolean> features = getDataFeatures(context);
        
        // 检查是否适合饼图
        if (categoryCount > 0 && categoryCount <= 8 && 
            features.getOrDefault("hasSingleValue", false)) {
            return ChartType.PIE;
        }
        
        // 检查是否适合散点图
        if (dataPointCount > 30 && 
            features.getOrDefault("hasWideRange", false)) {
            return ChartType.SCATTER;
        }
        
        // 检查是否适合折线图
        if (dataPointCount > 10 || categoryCount > 15) {
            return ChartType.LINE;
        }
        
        // 默认使用柱状图
        return ChartType.BAR;
    }
    
    /**
     * 根据图表类型记录信息到上下文
     * 
     * @param chartType 图表类型
     * @param context 配置上下文
     */
    public static void recordChartTypeInfo(ChartType chartType, ConfigurationContext context) {
        // 记录基本图表类型
        context.setChartType(chartType);
        context.addInfo("chartType", chartType.name());
        
        // 根据图表类型记录相关的可视化决策建议
        double chartRatioSuggestion = 0.75;  // 默认宽高比建议
        boolean needLegend = true;           // 是否需要图例
        
        switch (chartType) {
            case PIE:
                // 饼图通常需要更接近正方形的布局
                chartRatioSuggestion = 0.9;
                break;
            case BAR:
                // 柱状图通常宽一些
                chartRatioSuggestion = 0.65;
                break;
            case LINE:
                // 折线图通常也是横向布局
                chartRatioSuggestion = 0.6;
                break;
            case SCATTER:
                // 散点图通常接近正方形
                chartRatioSuggestion = 0.8;
                needLegend = false;  // 散点图通常不需要图例
                break;
            case RADAR:
                // 雷达图通常需要正方形布局
                chartRatioSuggestion = 1.0;
                break;
        }
        
        // 记录建议信息到上下文
        context.addInfo("suggestedAspectRatio", chartRatioSuggestion);
        context.addInfo("needsLegend", needLegend);
    }
} 